package com.wjr.braveheart.ui.mvp;

import android.content.Context;

import com.wjr.braveheart.utils.LogUtils;

import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;

/**
 * Created by WeiJinRan on 2018/1/24.
 * Email 994425089@qq.com.
 * Version 1.0
 * Describe: BasePresenter 抽象基类
 * PS: Not easy to write code, please indicate.
 */

public abstract class BasePresenter<M extends MvpBaseModel, V extends IMvpBaseView> {

    private V mProxyView;
    private M mModule;
    private SoftReference<V> mViewReference;

    /**
     * 绑定View
     */
    public void attach(V view) {
        this.mViewReference = new SoftReference<>(view);

        // 用代理对象
        mProxyView = (V) Proxy.newProxyInstance(
                view.getClass().getClassLoader(),
                view.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 执行这个方法 ，调用的是被代理的对象
                        if (!isViewAttached()) {
                            return null;
                        }
                        // 没解绑执行的是原始被代理 View 的方法
                        return method.invoke(mViewReference.get(), args);
                    }
                });

        /**
         *  使用反射，动态创建Model
         *  如果直接获取params中 model的Class 则不需要判断model是否继承了MvpBaseModel.class
         *  或者使用约束泛型 M extends MvpBaseModel 循环遍历params获取model的Class 通过反射创建model的实例
         *
         *  或者创建抽象方法实例化BasePresenter实例时在子类中实现该方法
         *  if (this.mModule == null) {
         *      this.mModule = createModule();
         *   }
         */
        Type[] params = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments();
        for (Type param : params) {
            //判断param是否是继承BaseModel
            // param instanceof MvpBaseModel
            //MvpBaseModel.class.isAssignableFrom((Class) param)
            if (MvpBaseModel.class.isAssignableFrom((Class<?>) param)) {
//                Log.d("BasePresenter", "param : " + ((Class) param).getSimpleName());
//                Log.d("BasePresenter", "param : " + ((Class) param).getName());
                try {
                    // 最好要判断一下类型
                    mModule = (M) ((Class<?>) param).newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                    LogUtils.e(e.getMessage());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    LogUtils.e(e.getMessage());
                }
            }
        }
    }

    /**
     * 解绑View
     */
    public void detach() {
        this.mModule = null;
        if (isViewAttached()) {
            mViewReference.clear();
            mViewReference = null;
        }
    }

    /**
     * 是否与View建立连接
     */
    protected boolean isViewAttached() {
        return mViewReference != null && mViewReference.get() != null;
    }

    protected V getView() {
        return mProxyView;
    }

    protected M getModule() {
        return mModule;
    }

    protected Context getContext() {
        return getView().getContext();
    }

}
